package com.infojarda.gbasedwiki.web.client;

import java.util.ArrayList;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.logical.shared.OpenEvent;
import com.google.gwt.event.logical.shared.OpenHandler;
import com.google.gwt.i18n.client.LocaleInfo;
import com.google.gwt.user.client.Random;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.DecoratedTabPanel;
import com.google.gwt.user.client.ui.DecoratorPanel;
import com.google.gwt.user.client.ui.DialogBox;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Hyperlink;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.RichTextArea;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.Tree;
import com.google.gwt.user.client.ui.TreeItem;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.infojarda.gbasedwiki.web.client.dtos.WikiPageDTO;
import com.infojarda.gbasedwiki.web.client.services.SettingService;
import com.infojarda.gbasedwiki.web.client.services.SettingServiceAsync;
import com.infojarda.gbasedwiki.web.client.services.WikiService;
import com.infojarda.gbasedwiki.web.client.services.WikiServiceAsync;
import com.infojarda.gbasedwiki.web.client.utils.RichTextToolbar;


public class Wiki implements EntryPoint{
	/**
	 * The message displayed to the user when the server cannot be reached or
	 * returns an error.
	 */
	private static final String SERVER_ERROR = "An error occurred while "
			+ "attempting to contact the server. Please check your network "
			+ "connection and try again.";
	/**	
	 * Create a remote service proxy to talk to the server-side WikiPage service
	 */
	private final WikiServiceAsync wikiService = GWT
		.create(WikiService.class);
	
	private final SettingServiceAsync settingService = GWT
	.create(SettingService.class);

	private WikiPageDTO pageUnderProcess;
	
	/**
	   * Create a dynamic tree that will add a random number of children to each
	   * node as it is clicked.
	   * 
	   * @return the new tree
	   */
	  private Tree createDynamicTree() {
	    // Create a new tree
	    Tree dynamicTree = new Tree();

	    // Add some default tree items
	    for (int i = 0; i < 5; i++) {
	      TreeItem item = dynamicTree.addItem("Tree" + " " + i);

	      // Temporarily add an item so we can expand this node
	      item.addItem("");
	    }

	    // Add a handler that automatically generates some children
	    dynamicTree.addOpenHandler(new OpenHandler<TreeItem>() {
	      public void onOpen(OpenEvent<TreeItem> event) {
	        TreeItem item = event.getTarget();
	        if (item.getChildCount() == 1) {
	          // Close the item immediately
	          item.setState(false, false);

	          // Add a random number of children to the item
	          String itemText = item.getText();
	          int numChildren = Random.nextInt(5) + 2;
	          for (int i = 0; i < numChildren; i++) {
	            TreeItem child = item.addItem(itemText + "." + i);
	            child.addItem("");
	          }

	          // Remove the temporary item when we finish loading
	          item.getChild(0).remove();

	          // Reopen the item
	          item.setState(true, false);
	        }
	      }
	    });

	    // Return the tree
	    return dynamicTree;
	  }



	  
	@Override
	public void onModuleLoad() {
	
		refreshRootWikiPageList();
		
		//get the value
	    settingService.readSetting("defaultHub", new AsyncCallback<String>(){

			@Override
			public void onFailure(Throwable caught) {
								
			}

			@Override
			public void onSuccess(String result) {
				readWikiPage(new Long(result));			
			}
		});
		
	    //readWikiPage(new Long(0));
	}
	
	private void processOptionsMenu(){
		VerticalPanel vPanel = new VerticalPanel();
	    vPanel.add(new HTML("Options"));
	    vPanel.setSpacing(5);
	    vPanel.setWidth("100%");
	    
	    //add the new link:
		
		Hyperlink creatRootPageHY = new Hyperlink("Create new hub", "#");
		Hyperlink creatRootPageHY2 = new Hyperlink("Settings", "#");
		
		creatRootPageHY.addClickHandler(new ClickHandler(){

			@Override
			public void onClick(ClickEvent event) {
				constructWikiTabPanel(null);
				//createNewRootWikiPage("new Page", "mosyi", new Long(0), "Content");					
			}
		
		});
		
		creatRootPageHY2.addClickHandler(new ClickHandler(){

			@Override
			public void onClick(ClickEvent event) {
				
				
				RootPanel.get("ContentContainer").clear();
			    RootPanel.get("ContentContainer").add(constructSettingsTabPanel());
			}
		
		});
		vPanel.add(creatRootPageHY);
		vPanel.add(creatRootPageHY2);
		// Wrap the content in a DecoratorPanel
	    DecoratorPanel decPanel = new DecoratorPanel();
	    decPanel.setWidget(vPanel);
	    RootPanel.get("SideContainer").add(decPanel);
	    
	}
	
	private void processRootWikiPagesList(ArrayList<WikiPageDTO> result){
		HTML headerTemp = new HTML("Welcome to Google based wiki!");
		Image image = new Image("200.jpg");
		image.setStyleName("logo");
	    headerTemp.setHeight("35px");
  
	    VerticalPanel vPanel = new VerticalPanel();
	    vPanel.add(new HTML("Wiki Hubs"));	    

	    vPanel.setSpacing(5);
	    vPanel.setWidth("100%");
		for (WikiPageDTO wikiPageDTO : result) {
			Hyperlink hy = new Hyperlink(wikiPageDTO.getPageTitle(), "#");
			final Long id = wikiPageDTO.getId();
			hy.addClickHandler(new ClickHandler(){

				@Override
				public void onClick(ClickEvent event) {
					readWikiPage(id);					
				}
			
			});
			vPanel.add(hy);
		}
		
			    
	 // Wrap the content in a DecoratorPanel
	    DecoratorPanel decPanel = new DecoratorPanel();
	    decPanel.setWidget(vPanel);
	    
	    RootPanel.get("SideContainer").clear();
	    RootPanel.get("SideContainer").add(image);
	    RootPanel.get("SideContainer").add(headerTemp);
	    RootPanel.get("SideContainer").add(decPanel);
	    RootPanel.get("SideContainer").add(new HTML("<br/>"));
	    processOptionsMenu();
		
	}
	
	private void createNewRootWikiPage(String pageTitle, String author, Long parent, String content){
		WikiPageDTO wikiPageDTO = new WikiPageDTO();
		wikiPageDTO.setAuthor(author);
		wikiPageDTO.setPageTitle(pageTitle);
		wikiPageDTO.setParentId(parent);
		wikiPageDTO.setContent(content);
		
		wikiService.createWikiPage(wikiPageDTO,  new AsyncCallback<Long>() {
			public void onFailure(Throwable caught) {
				// Show the RPC error message to the user
				GWT.log("failed", null);  
			}
			
			@Override
			public void onSuccess(Long result) {				
				refreshRootWikiPageList();
				if (!result.equals(new Long(-1)))
					readWikiPage(result);
			}
		});
	}
	
	private void refreshRootWikiPageList(){
		wikiService.getRootWikiPages(new AsyncCallback<ArrayList<WikiPageDTO>>() {
			public void onFailure(Throwable caught) {
				// Show the RPC error message to the user
				GWT.log("failed", null);  
			}

			public void onSuccess(ArrayList<WikiPageDTO> result) {
				GWT.log("success", null); 
				processRootWikiPagesList(result);
				
			}
		});

	}
	
	private void readWikiPage(Long id){
		//here we read the page content!
	    wikiService.getWikiPage(id, new AsyncCallback<WikiPageDTO>() {
			public void onFailure(Throwable caught) {
				// Show the RPC error message to the user
				GWT.log("failed", null);  
			}

			public void onSuccess(ArrayList<WikiPageDTO> result) {
				processRootWikiPagesList(result);
				
			}

			@Override
			public void onSuccess(WikiPageDTO result) {
				GWT.log("success", null); 
				GWT.log(result.toString(), null);
				processWikiPage(result);
			}
		});
	}
	
	/**
	   * Create the dialog box for this example.
	   * 
	   * @return the new dialog box
	   */
	  private DialogBox createDialogBox() {
	    // Create a dialog box and set the caption text
	    final DialogBox dialogBox = new DialogBox();
	    dialogBox.ensureDebugId("cwDialogBox");
	    dialogBox.setText("Delete confirmation popup");

	    // Create a table to layout the content
	    VerticalPanel dialogContents = new VerticalPanel();
	    dialogContents.setSpacing(4);
	    dialogBox.setWidget(dialogContents);

	    // Add some text to the top of the dialog
	    HTML details = new HTML("Are you sure you want to delete this page?");
	    dialogContents.add(details);
	    dialogContents.setCellHorizontalAlignment(details,
	        HasHorizontalAlignment.ALIGN_CENTER);

	    HorizontalPanel dialogContents2 = new HorizontalPanel();
	    dialogContents2.setSpacing(4);
	    dialogContents.add(dialogContents2);
	    
	    
	    // Add a close button at the bottom of the dialog
	    Button closeButton = new Button("Delete",
	        new ClickHandler() {
	          public void onClick(ClickEvent event) {
	            dialogBox.hide();
	            deleteWikiPage(pageUnderProcess.getId());
	          }
	        });
	    dialogContents2.add(closeButton);
	    
	 // Add a close button at the bottom of the dialog
	    Button closeButton2 = new Button("Cancel",
	        new ClickHandler() {
	          public void onClick(ClickEvent event) {
	            dialogBox.hide();
	          }
	        });
	    dialogContents2.add(closeButton2);
	    
	    
	    if (LocaleInfo.getCurrentLocale().isRTL()) {
	      dialogContents.setCellHorizontalAlignment(closeButton,
	          HasHorizontalAlignment.ALIGN_LEFT);

	    } else {
	      dialogContents.setCellHorizontalAlignment(closeButton,
	          HasHorizontalAlignment.ALIGN_RIGHT);
	    }

	    // Return the dialog box
	    return dialogBox;
	  }

	private void deleteWikiPage(Long id){
		wikiService.deleteWikiPage(id, new AsyncCallback<String>() {
			public void onFailure(Throwable caught) {
				// Show the RPC error message to the user
				Window.alert("Failed to delete wiki page!");
			}
			
			@Override
			public void onSuccess(String result) {				
				refreshRootWikiPageList();
				Window.alert("Success!");
			}
		});
	}
	
	private void updateWikiPage(){
		wikiService.updateWikiPage(pageUnderProcess, new AsyncCallback<String>(){

			@Override
			public void onFailure(Throwable caught) {
				Window.alert("Failed to update wiki content!");
				
			}

			@Override
			public void onSuccess(String result) {
				Window.alert("Success!");
				readWikiPage(pageUnderProcess.getId());
			}
		});
	}
	
	private DecoratedTabPanel constructWikiTabPanel(WikiPageDTO wikiPageDTO){
		// Tabs titles
		String[] tabTitles = {"Display", "Edit"};
		
		// Create a tab panel Widget Object
	    DecoratedTabPanel tabPanel = new DecoratedTabPanel();
	    tabPanel.setWidth("100%");
	    tabPanel.setAnimationEnabled(false);
	    
	    final TextBox pageTitleText = new TextBox();
	    final TextBox authorText = new TextBox();
	    
	    if(wikiPageDTO != null){
	    	pageUnderProcess = wikiPageDTO;
	    	// Home Tab
	    	HTML homeText = new HTML(wikiPageDTO.getContent());
	    	tabPanel.add(homeText, tabTitles[0]);
	    	
	    	// Edit Tab
	    	// Create the text area and toolbar
		    pageTitleText.setText(pageUnderProcess.getPageTitle());
		    authorText.setText(pageUnderProcess.getAuthor());
		    
	    	final RichTextArea area = new RichTextArea();
		    area.ensureDebugId("cwRichText-area");
		    area.setSize("100%", "14em");
		    area.setHTML(wikiPageDTO.getContent());
		    area.setTitle("TextArea");
		    
		    RichTextToolbar toolbar = new RichTextToolbar(area);
		    toolbar.ensureDebugId("cwRichText-toolbar");
		    toolbar.setWidth("100%");
		    
		    // Create the dialog box
		    final DialogBox dialogBox = createDialogBox();
		    dialogBox.setAnimationEnabled(true);
	    	
		    // Add a normal button
		    Button normalButton = new Button("Delete Current Page",
		        new ClickHandler() {
		          public void onClick(ClickEvent event) {
		        	  dialogBox.center();
		              dialogBox.show();
		          }
		        });
		    // Add a normal button
		    Button saveButton = new Button("Save Page",
		        new ClickHandler() {
		          public void onClick(ClickEvent event) {

		        	  pageUnderProcess.setContent(area.getHTML());
		        	  
		        	  updateWikiPage();
		          }
		        });
		    
		    // Add the components to a panel
		    Grid gridHeaderData = new Grid(2, 2);
		    gridHeaderData.setStyleName("cw-RichText");
		    gridHeaderData.setWidget(0, 0, new HTML("Page Title: "));
		    gridHeaderData.setWidget(0, 1, authorText);
		    gridHeaderData.setWidget(1, 0, new HTML("Author: "));
		    gridHeaderData.setWidget(1, 1, pageTitleText);
		    
		    // Add the components to a panel
		    Grid gridFooterData = new Grid(1, 2);
		    gridFooterData.setStyleName("cw-RichText");
		    gridFooterData.setWidget(0, 0, normalButton);
		    gridFooterData.setWidget(0, 1, saveButton);
		    
		    
		    // Add the components to a panel
		    Grid grid = new Grid(4, 1);
		    grid.setStyleName("cw-RichText");
		    grid.setWidget(0, 0, gridHeaderData);
		    grid.setWidget(1, 0, toolbar);
		    grid.setWidget(2, 0, area);
		    grid.setWidget(3, 0, gridFooterData);		   
		    
		    tabPanel.add(grid, tabTitles[1]);
		    
		    tabPanel.selectTab(0);
		    RootPanel.get("ContentContainer").clear();
		    RootPanel.get("ContentContainer").add(tabPanel);
		    
	    } else {
	    	final WikiPageDTO wikiPageDTO2 = new WikiPageDTO();
	    	pageUnderProcess = wikiPageDTO2;
	    	
	    	// Home Tab
	    	HTML homeText = new HTML(wikiPageDTO2.getContent());
	    	tabPanel.add(homeText, tabTitles[0]);
	    	
	    	// Edit Tab
	    	// Create the text area and toolbar
		    final RichTextArea area = new RichTextArea();
		    area.ensureDebugId("cwRichText-area");
		    area.setSize("100%", "14em");
		    area.setHTML(wikiPageDTO2.getContent());
		    area.setTitle("TextArea");
		    
		    RichTextToolbar toolbar = new RichTextToolbar(area);
		    toolbar.ensureDebugId("cwRichText-toolbar");
		    toolbar.setWidth("100%");
		    
		    // Create the dialog box
		    final DialogBox dialogBox = createDialogBox();
		    dialogBox.setAnimationEnabled(true);
	    	
		    // Add a normal button
		    Button normalButton = new Button("Discart",
		        new ClickHandler() {
		          public void onClick(ClickEvent event) {
		        	  dialogBox.center();
		              dialogBox.show();
		          }
		        });
		    
		   
		    // Add a normal button
		    Button saveButton = new Button("Save Page",
		        new ClickHandler() {
		          public void onClick(ClickEvent event) {

		        	  pageUnderProcess.setContent(area.getHTML());
		        	  
		        	  wikiPageDTO2.setAuthor(authorText.getText());
		        	  wikiPageDTO2.setPageTitle(pageTitleText.getText());
		        	  
		        	  //updateWikiPage();
		        	  createNewRootWikiPage( wikiPageDTO2.getAuthor(), wikiPageDTO2.getPageTitle(), new Long(0), wikiPageDTO2.getContent());
		          }
		        });
		    
		 // Add the components to a panel
		    Grid gridHeaderData = new Grid(2, 2);
		    gridHeaderData.setStyleName("cw-RichText");
		    gridHeaderData.setWidget(0, 0, new HTML("Page Title: "));
		    gridHeaderData.setWidget(0, 1, authorText);
		    gridHeaderData.setWidget(1, 0, new HTML("Author: "));
		    gridHeaderData.setWidget(1, 1, pageTitleText);
		    
		    // Add the components to a panel
		    Grid gridFooterData = new Grid(1, 2);
		    gridFooterData.setStyleName("cw-RichText");
		    gridFooterData.setWidget(0, 0, normalButton);
		    gridFooterData.setWidget(0, 1, saveButton);
		    
		    
		    // Add the components to a panel
		    Grid grid = new Grid(4, 1);
		    grid.setStyleName("cw-RichText");
		    grid.setWidget(0, 0, gridHeaderData);
		    grid.setWidget(1, 0, toolbar);
		    grid.setWidget(2, 0, area);
		    grid.setWidget(3, 0, gridFooterData);	
		    
		    tabPanel.add(grid, tabTitles[1]);
		    
		    tabPanel.selectTab(1);
		    RootPanel.get("ContentContainer").clear();
		    RootPanel.get("ContentContainer").add(tabPanel);
	    }
	    
	    
		return tabPanel;
	}
	
	private DecoratedTabPanel constructSettingsTabPanel(){
		// Tabs titles
		String[] tabTitles = {"Settings"};
		
		// Create a tab panel Widget Object
	    DecoratedTabPanel tabPanel = new DecoratedTabPanel();
	    tabPanel.setWidth("100%");
	    tabPanel.setAnimationEnabled(false);
	    // Settings Tab
	    final TextBox defaultHub = new TextBox();
	    
	    //get the value
	    settingService.readSetting("defaultHub", new AsyncCallback<String>(){

			@Override
			public void onFailure(Throwable caught) {
								
			}

			@Override
			public void onSuccess(String result) {
				defaultHub.setText(result);			
			}
		});
	    
	    	// Add a normal button
		    Button saveButton = new Button("Save",
		        new ClickHandler() {
		          public void onClick(ClickEvent event) {

		        	//get the value
		      	    settingService.writeStting("defaultHub", defaultHub.getText(), new AsyncCallback<String>(){

		      			@Override
		      			public void onFailure(Throwable caught) {
		      								
		      			}

		      			@Override
		      			public void onSuccess(String result) {
		      						
		      			}
		      		});
		      	    
		          }
		        });
		    
		    // Add the components to a panel
		    Grid gridHeaderData = new Grid(2, 2);
		    gridHeaderData.setStyleName("cw-RichText");
		    gridHeaderData.setWidget(0, 0, new HTML("Default Hub to load: "));
		    gridHeaderData.setWidget(0, 1, defaultHub);
		    gridHeaderData.setWidget(1, 1, saveButton);

		    tabPanel.add(gridHeaderData, tabTitles[0]);
		    
		    tabPanel.selectTab(0);

	    
		return tabPanel;
	}
	
	private void processWikiPage(WikiPageDTO wikiPageDTO){		
		constructWikiTabPanel(wikiPageDTO);
	}
	

	
	private static String getShortBogusMarkup() {   
        return "<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. " +   
                "Sed metus nibh, sodales a, porta at, vulputate eget, dui.  " +   
                "In pellentesque nisl non sem. Suspendisse nunc sem, pretium eget, " +   
                "cursus a, fringilla vel, urna.";   
    }

}

